package org.dftproject.genesis.ui.pages.pedigree.zoom;

import java.util.LinkedList;
import java.util.List;

import org.dftproject.genesis.ui.figures.zoompan.ZoomPanContainer;
import org.eclipse.draw2d.Viewport;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PrecisionPoint;

public class ZoomManager {
	
	private final ZoomPanContainer target;
	private final Viewport viewport;
	
	private final float scaleBase = 1.5f;
	
	private final int minExponent = -10;
	private final int maxExponent = 0;
	private float exponent = 0;
	
	private final List<IZoomListener> listeners = new LinkedList<IZoomListener>();

	public ZoomManager(ZoomPanContainer parent) {
		this.target = parent;
		this.viewport = parent.getViewport();
	}
	
	public void setExponent(float exponent) {
		setExponent(exponent, viewport.getBounds().getCenter());
	}
	
	public void setExponent(float exponent, Point center) {
		PrecisionPoint oldCenter = new PrecisionPoint(center);
		target.translateToRelative(oldCenter);
		oldCenter.translate(target.getBounds().getLocation());

		PrecisionPoint relativeCenter = new PrecisionPoint(oldCenter);
		relativeCenter.performScale(1 / target.getScale());
		
		this.exponent = exponent;
		if (this.exponent < minExponent)
			this.exponent = minExponent;
		if (this.exponent > maxExponent)
			this.exponent = maxExponent;
		
		target.setScale(Math.pow(scaleBase, this.exponent));
		
		PrecisionPoint newCenter = new PrecisionPoint(relativeCenter);
		newCenter.performScale(target.getScale());
		
		Dimension offset = newCenter.getDifference(oldCenter);
		viewport.setViewLocation(viewport.getViewLocation().getTranslated(offset));
		
		notifyExponentChanged();
		
		/*// Change the scale of the target figure
		
		double oldScale = target.getScale();
		this.exponent = exponent;
		if (this.exponent < minExponent)
			this.exponent = minExponent;
		if (this.exponent > maxExponent)
			this.exponent = maxExponent;
		double newScale = Math.pow(scaleBase, this.exponent);
		target.setScale(newScale);
		
		// Reposition the viewport

		viewport.setViewCenter(new Point(center.x * newScale / oldScale, center.y * newScale / oldScale));
		
		// Notify listeners
		
		notifyExponentChanged();*/
	}
	
	public float getExponent() {
		return exponent;
	}

	public int getMinExponent() {
		return minExponent;
	}
	
	public int getMaxExponent() {
		return maxExponent;
	}
	
	public void addListener(IZoomListener listener) {
		listeners.add(listener);
	}
	
	public void removeListener(IZoomListener listener) {
		listeners.remove(listener);
	}
	
	protected void notifyExponentChanged() {
		for (IZoomListener listener : listeners)
			listener.exponentChanged(this, exponent);
	}

	public float getScaleBase() {
		return scaleBase;
	}
	
}
